//通用函数

#define PI 3.1415926

float RadicalInverse_VdC(uint bits)
{
	bits = (bits << 16u) | (bits >> 16u);
	bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
	bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
	bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
	bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
	return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
// ----------------------------------------------------------------------------
float2 Hammersley(uint i, uint N)
{
	return float2(float(i) / float(N), RadicalInverse_VdC(i));
}

float chi(float v)
{
	return v > 0 ? 1 : 0;
}

//将一个三维方向转换为采样Panorama贴图的UV
float2 PanoramaUV(float3 direction)
{
	//用极坐标作为采样Panorama贴图的UV

	//首先，以下面的对应关系来构建一个极坐标系：
	//Y轴正方向 = 极轴的正方向（“向上”的方向）
	//Z轴正方向 = 方位角为0度的方向

	//使用正弦来计算极角
	//极角，弧度制，范围[-pi/2,pi/2]：
	float polar = asin(direction.y / length(direction));

	//先算出与Z轴正方向的夹角：
	float angle_between_Z = acos(direction.z / length(direction.xz));
	//由于Z轴正方向两边的角度是镜像的，所以需要再乘算上X方向的正负性来做区分才能算出方位角
	//方位角，弧度制，范围[-pi,pi]：
	float azimuth = angle_between_Z * (direction.x / abs(direction.x));

	//将极坐标转换为采样2D贴图的坐标：
	float2 result;
	result.x = azimuth / PI / 2 + 0.5;  //将方位角范围映射到[0,1]
	result.y = 1.0 - (polar / PI + 0.5);//先将极角范围映射到[0,1]，然后再翻转，因为V的正方向朝下

	return result;
}